home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Add-Ons / 4D / ComboBox 1.1.1 / src / ComboBoxArea.c < prev    next >
Text File  |  1996-02-23  |  32KB  |  1,142 lines

  1. //---------------------------------------------------------------------------------------
  2. //
  3. //    ComboBoxArea.c -- Source for ComboBox external area event handler
  4. //
  5. //    Copyright ©1995-1996, Pensacola Christian College
  6. //
  7. //    ======================================================================
  8. //    Change History
  9. //    ======================================================================
  10. //
  11. //    1.0            08/  /95        Steve Dwire
  12. //                                            Initial release
  13. //
  14. //    1.0.1        10/18/95        Steve Dwire
  15. //                                            Fix problem of losing Modified flag in AreaSelect()
  16. //
  17. //    1.1 a1    10/23/95        Steve Dwire
  18. //                                            Keep ComboBox from swallowing Enter key
  19. //
  20. //                    10/25/95        Steve Dwire
  21. //                                            Fix problem of dead scroll bars resulting from more than one
  22. //                                            active list in the list window at one time (One list area seems
  23. //                                            to remain active from initialization, still.  Needs to be fixed)
  24. //
  25. //                    10/26/95        Steve Dwire
  26. //                                            Make closing the List call the script
  27. //
  28. //    1.1            11/17/95        Steve Dwire
  29. //                                            Because kCallTheScript can be passed only from a user event in
  30. //                                            the main process, I can't call the script directly when the user
  31. //                                            clicks in the list window to close it.  So I'm making 
  32. //                                            AreaHideList() post a unique keystroke (command-@, without shift)
  33. //                                            as an autoKey event.  When I get that autokeystroke, I will pass
  34. //                                            back kCallTheScript.  By making this an autoKey instead of a
  35. //                                            keyDown event, I allow a command-@ keystroke to be passed for
  36. //                                            those who have keyboards that will actually let them type one
  37. //                                            without using the shift key.
  38. //
  39. //    1.1.1a1    02/20/96        Steve Dwire
  40. //                                            Fix crash revealed with Charlie Rieman's "Less-Obnoxious Bus
  41. //                                            Error" control panel.
  42. //
  43. //    1.1.1a2    02/23/96        Steve Dwire
  44. //                                            Keep from swallowing Escape key and putting that ugly "dunno"
  45. //                                            box in the text field.  Without this change, using Customiser
  46. //                                            to make Escape cancel a layout didn't work when a ComboBox
  47. //                                            was active.
  48. //
  49. //---------------------------------------------------------------------------------------
  50.  
  51. #include <Ext4D.h>
  52. #include <QuickDraw.h>
  53. #include <Palettes.h>
  54. #include <ctype.h>
  55. #include <stddef.h>
  56. #include "ComboBoxMain.h"
  57. #include "ComboBoxListMouseDown.h" // To pass on mousedown event to list
  58.  
  59.  
  60. //---------------------------------------------------------------------------------
  61. //
  62. // FUNCTION: Area
  63. //
  64. //---------------------------------------------------------------------------------
  65.  
  66. //External area dispatcher
  67. OSErr Area(EventRecord *event, Rect *bounds, UBYTE *name, AreaHnd *AreaData)
  68. {
  69.     OSErr err;
  70.  
  71.     err = noErr;
  72.     // Do we have an area data handle?
  73.     if(*AreaData) 
  74.         switch(event->what)
  75.         {
  76.             //•Delete code handling events you do not wish to take
  77.             case kIdleEvt:
  78.                 if ((**AreaData)->TextTEHnd && (**AreaData)->Flags.CanEdit)
  79.                     TEIdle((**AreaData)->TextTEHnd);
  80.                 break;
  81.             
  82.             case kCursorEvt:
  83.                 AreaCursor(*((AreaHnd*)AreaData), event);
  84.                 //•Set the cursor to what it should be while over your area.
  85.                 break;
  86.             
  87.             case mouseDown:
  88.                 //SysBeep(10);
  89.                 AreaMouseDown(*((AreaHnd*)AreaData), event);
  90.                 break;
  91.                 
  92.             case kScrollEvt:
  93.             case updateEvt:
  94.                 //•Recalculate your bounding rectangle
  95.                 AreaScrollRect(*((AreaHnd*)AreaData), bounds);
  96.                 //•Redraw your area if need be
  97.                 if(event->what == updateEvt)
  98.                     AreaUpdate(*((AreaHnd*)AreaData), event);
  99.                 break;
  100.                 
  101.             case keyDown:
  102.                 //v1.1
  103.                 // added the following lines:
  104.                 AreaKeyDown(*((AreaHnd*)AreaData), event);
  105.                 break;
  106.                 // to separate autoKey from keyDown.
  107.                 
  108.             case autoKey:
  109.                 //v1.1
  110.                 // added the following lines:
  111.                 if (((SBYTE)LoWord(event->message & charCodeMask) == '@') &&    
  112.                         (event->modifiers == cmdKey)) // this is our command-@ w/o shift keystroke
  113.                 {
  114.                     ParameterBlock    block; // moved from AreaHideList
  115.                     PackHnd                    PackDataHnd;
  116.                     
  117.                     PackDataHnd = GetPackDataHnd();
  118.                     block.fParam1 = (*PackDataHnd)->ListProcID; // moved from AreaHideList
  119.                     CALL4D(kEX_FREEZE_PROCESS,&block); // moved from AreaHideList
  120.                     event->message = kCallTheScript;
  121.                 }
  122.                 else
  123.                 // to process the command-@ autokey
  124.                     AreaKeyDown(*((AreaHnd*)AreaData), event);
  125.                 break;
  126.                 
  127.             case kSelectEvt:
  128.                 //•Delete this code if area cannot be selected
  129.                 err = AreaSelect(*((AreaHnd*)AreaData), event);
  130.                 break;
  131.                 
  132.             case kDeSelectEvt:
  133.                 //•Delete this code if area cannot be selected
  134.                 //•If cannot deselect yet, uncomment next line
  135.                 //event->message = kZoneRefuse;
  136.                 AreaDeselect(*((AreaHnd*)AreaData));
  137.                 break;
  138.                 
  139.             //case kResizeEvt:
  140.                 //•{Does this only happen for external windows?}
  141.                 //break;
  142.                 
  143.             //case kTestPrintSizeEvt:
  144.                 //•If this is a variable frame area, uncomment the next line
  145.                 //event->message = kZoneVariableFrame;
  146.                 //break;
  147.                 
  148.             //case kPrintSizeEvt:
  149.             //    event->message = //*size of area left to print (in points)
  150.             //    break;
  151.                 
  152.             //case kPrintBandEvt:
  153.                 //•It's time to print your area
  154.                 //break;
  155.                 
  156.             //case kUndoEvt:
  157.                 //•User chose “Undo” from “Edit” menu.
  158.                 //break;
  159.                 
  160.             //v1.1
  161.             // Moved kStructEvt outside if because AreaHnd is invalid for kStructEvt.
  162.                 
  163.             case kCutEvt:
  164.                 //•User chose “Cut” from “Edit” menu.
  165.                 AreaCut(*((AreaHnd*)AreaData));
  166.                 break;
  167.                 
  168.             case kCopyEvt:
  169.                 //•User chose “Copy” from “Edit” menu.
  170.                 AreaCopy(*((AreaHnd*)AreaData));
  171.                 break;
  172.                 
  173.             case kPasteEvt:
  174.                 //•User chose “Paste” from “Edit” menu.
  175.                 AreaPaste(*((AreaHnd*)AreaData));
  176.                 break;
  177.                 
  178.             case kClearEvt:
  179.                 //•User chose “Clear” from “Edit” menu.
  180.                 AreaClear(*((AreaHnd*)AreaData));
  181.                 break;
  182.                 
  183.             case kSelectAllEvt:
  184.                 //•User chose “SelectAll” from “Edit” menu.
  185.                 AreaSelectAll(*((AreaHnd*)AreaData));
  186.                 break;
  187.                 
  188.             //case kInstallMenusEvt:
  189.                 //•Install your area’s menus into the current menu bar.
  190.                 //break;
  191.                 
  192.             //case kDeInstallMenusEvt:
  193.                 //•Remove your area’s menus from the current menu bar.
  194.                 //break;
  195.                 
  196.             //case kMenuSelectedEvt:
  197.                 //•Someone chose one of your area’s menu items.
  198.                 //•{Where do we get info on which item was chosen?}
  199.                 //break;
  200.                 
  201.             //case kActivateMenusEvt:
  202.                 //•{Not sure what this does.}
  203.                 //event->message = kEventNotTaken;
  204.                 //break;
  205.                 
  206.             //case kGrowBoxEvt:
  207.                 //•If you need to limit the minimum size, uncomment the next lines
  208.                 //event->modifiers = kNeedMinSize;
  209.                 //event->message = /*Width & Height*/; //•{How do we encode this?}
  210.                 //break;
  211.                                 
  212.             case kTestEvt:
  213.                 //•If area can be selected, uncomment next line. 
  214.                 if ((**AreaData)->Flags.Enabled)
  215.                     event->message = kZoneCanBeSelected;
  216.                 //•If area should be kept offscreen, uncomment next line.
  217.                 //event->message = kUseOffScreen;
  218.                 break;
  219.                 
  220.             default:
  221.                 //we don't handle anything else.
  222.                 event->message = kEventNotTaken;
  223.                 break;
  224.         }
  225.     else 
  226.         event->message = kEventNotTaken;
  227.     return err;
  228. }
  229.  
  230.  
  231. //---------------------------------------------------------------------------------
  232. //
  233. // FUNCTION: AreaCursor
  234. //
  235. //---------------------------------------------------------------------------------
  236.  
  237. void AreaCursor(AreaHnd AreaData, EventRecord* event)
  238. {
  239.     switch(GetMouseLoc(AreaData,event))
  240.     {
  241.         case kInText:
  242.             if((*AreaData)->Flags.Active && (*AreaData)->Flags.CanEdit)
  243.                 SetCursor(*GetCursor(iBeamCursor));
  244.             else
  245.                 SetCursor(*GetCursor(GetResID('4BNX','CURS',1))); // standard arrow
  246.             break;
  247.         default:
  248.             SetCursor(*GetCursor(GetResID('4BNX','CURS',1))); // standard arrow
  249.     }
  250. }
  251.  
  252.  
  253. //---------------------------------------------------------------------------------
  254. //
  255. // FUNCTION: AreaMouseDown
  256. //
  257. //---------------------------------------------------------------------------------
  258.  
  259. void AreaMouseDown(AreaHnd AreaData, EventRecord* event)
  260. {
  261.     MouseLocType    MouseLoc;
  262.     ColorSpec            OldFore, OldBack;
  263.     Boolean                WaitMouse;
  264.     
  265.     WaitMouse = false;
  266.     
  267.     if((*AreaData)->Flags.Enabled)
  268.     {
  269.         if(TickCount() - (*AreaData)->ActivateTick > GetDblTime())
  270.         {
  271.             MouseLoc = GetMouseLoc(AreaData, event);
  272.             switch(MouseLoc)
  273.             {
  274.                 case kInText:
  275.                     SaveFore(&OldFore);
  276.                     SaveBack(&OldBack);
  277.                     PmForeColor((*AreaData)->TextFGColor);
  278.                     PmBackColor((*AreaData)->TextBGColor);
  279.                     if ((*AreaData)->Flags.CanEdit)
  280.                         TEClick(event->where,(event->modifiers & shiftKey),(*AreaData)->TextTEHnd);
  281.                     else if((*AreaData)->Flags.CanList)
  282.                     {
  283.                         AreaShowList(AreaData);
  284.                         WaitMouse = true;
  285.                     }
  286.                     RestoreFore(&OldFore);
  287.                     RestoreBack(&OldBack);
  288.                     break;
  289.                 case kInPICT:
  290.                     if((*AreaData)->Flags.Open)
  291.                     //v1.1
  292.                     // removed the following lines from v1.1 a1:
  293.                     //{
  294.                     //    event->message = kCallTheScript;
  295.                     // because AreaHideList() takes care of it for us
  296.                         
  297.                         AreaHideList(AreaData);
  298.                     //v1.1
  299.                     // removed the following line from v1.1 a1:
  300.                     //}
  301.                     // self-explanatory.
  302.                     else if((*AreaData)->Flags.CanList)
  303.                     {
  304.                         AreaShowList(AreaData);
  305.                         WaitMouse = true;
  306.                     }
  307.                     break;
  308.                 default:
  309.                     //v1.1
  310.                     // removed the following lines from v1.1 a1:
  311.                     //if ((*AreaData)->Flags.Open)
  312.                     //{
  313.                     //    event->message = kCallTheScript;
  314.                     // because AreaHideList() takes care of it for us
  315.                     
  316.                         AreaHideList(AreaData);
  317.                     //v1.1
  318.                     // removed the following lines from v1.1 a1:
  319.                     //}
  320.                     //else
  321.                     // because they're no longer necessary
  322.                         event->message = kEventNotTaken;
  323.             }
  324.         }
  325.         else if ((*AreaData)->Flags.ListOnActivate)
  326.             WaitMouse = true;
  327.         if (WaitMouse)
  328.         {
  329.             ParameterBlock    block;
  330.             Point                        MousePt;
  331.             EventRecord            FakeEvent; // to pass mouse point to ListMouseDown()
  332.             WindowPtr                ListWindow;
  333.             
  334.             ListWindow = (*GetPackDataHnd())->ListWindow;
  335.             AreaUpdate(AreaData,event);
  336.             while (StillDown())
  337.             {
  338.                 // If they ever wander over the list area, LClick() there.
  339.                 CALL4D(kEX_YIELD_ABSOLUTE,&block);
  340.                 CALL4D(kEX_YIELD_ABSOLUTE,&block); // Give the list process a chance
  341.                 CALL4D(kEX_YIELD_ABSOLUTE,&block); // to update its list window
  342.                 GetMouse(&MousePt);
  343.                 LocalToGlobal(&MousePt);
  344.                 if ((MousePt.h >= (*AreaData)->ListRect.left) &&
  345.                         (MousePt.h <= (*AreaData)->ListRect.right - kScrollBarWidth) &&
  346.                         (MousePt.v >= (*AreaData)->ListRect.top) &&
  347.                         (MousePt.v <= (*AreaData)->ListRect.bottom))
  348.                 {
  349.                     FakeEvent.where = MousePt;
  350.                     
  351.                     //v1.1
  352.                     // removed the following line from v1.1 a1:
  353.                     //FakeEvent.message = event->message;
  354.                     // since ListMouseDown() no longer changes the message parameter to kCallTheScript
  355.                     
  356.                     ListMouseDown (AreaData,&FakeEvent,ListWindow);
  357.                     
  358.                     //v1.1
  359.                     // removed the following line from v1.1 a1:
  360.                     //event->message = FakeEvent.message;
  361.                     // since ListMouseDown() no longer changes the message paramter to kCallTheScript
  362.                     
  363.                 }
  364.             }
  365.         }
  366.     }
  367.     else
  368.         event->message = kEventNotTaken;
  369.         
  370.     (*AreaData)->ActivateTick = 0;    
  371. }
  372.  
  373.  
  374. //---------------------------------------------------------------------------------
  375. //
  376. // FUNCTION: AreaScrollRect
  377. //
  378. //---------------------------------------------------------------------------------
  379.  
  380. void AreaScrollRect(AreaHnd AreaDataHnd, Rect* AreaRect)
  381. {
  382.     SLONG    diffX, diffY;
  383.     AreaPtr    AreaDataPtr;
  384.     
  385.     HLock((Handle)AreaDataHnd);
  386.     AreaDataPtr = *AreaDataHnd;
  387.     diffX = AreaRect->left - AreaDataPtr->AreaRect.left;
  388.     diffY = AreaRect->top - AreaDataPtr->AreaRect.top;
  389.     
  390.     if(diffX || diffY) //we moved
  391.     {    
  392.         BlockMove(AreaRect, &(AreaDataPtr->AreaRect), sizeof(Rect));
  393.         OffsetRect(&(AreaDataPtr->PICTRect),diffX,diffY);
  394.         OffsetRect(&(AreaDataPtr->TextRect),diffX,diffY);
  395.         CalcListRect(AreaDataPtr);
  396.         CalcTextRect(AreaDataPtr);
  397.     }
  398.     HUnlock((Handle)AreaDataHnd);
  399.     if(diffX || diffY) //we moved
  400.         AreaHideList(AreaDataHnd);
  401. }
  402.  
  403.  
  404. //---------------------------------------------------------------------------------
  405. //
  406. // FUNCTION: AreaUpdate
  407. //
  408. //---------------------------------------------------------------------------------
  409.  
  410. void AreaUpdate(AreaHnd AreaData, EventRecord* event)
  411. {
  412.     AreaPtr        AreaDataPtr;
  413.     GrafPtr        savePort;
  414.     TEHandle    text;
  415.     Boolean        IsColorQD;
  416.     PicHandle    ThePICT;
  417.     ColorSpec    OldFore, OldBack;
  418.     
  419.     HLock((Handle)AreaData);
  420.     AreaDataPtr = *AreaData;
  421.     
  422.     GetPort(&savePort);
  423.     IsColorQD = ((((CGrafPtr)savePort)->portVersion & 0xC000) == 0xC000);
  424.     
  425.     if (IsColorQD)
  426.     {
  427.         if ((!AreaDataPtr->Flags.Enabled) && (AreaDataPtr->CPICTResDis != (-1)))
  428.           ThePICT = GetPicture(AreaDataPtr->CPICTResDis);
  429.       else
  430.       {
  431.         if (AreaDataPtr->Flags.Open)
  432.           ThePICT = GetPicture(AreaDataPtr->CPICTResDn);
  433.         else
  434.             ThePICT = GetPicture(AreaDataPtr->CPICTResUp);
  435.       }
  436.     }
  437.     else
  438.     {
  439.         if ((!AreaDataPtr->Flags.Enabled) && (AreaDataPtr->MPICTResDis != (-1)))
  440.           ThePICT = GetPicture(AreaDataPtr->MPICTResDis);
  441.       else
  442.       {
  443.         if (AreaDataPtr->Flags.Open)
  444.           ThePICT = GetPicture(AreaDataPtr->MPICTResDn);
  445.         else
  446.             ThePICT = GetPicture(AreaDataPtr->MPICTResUp);
  447.       }
  448.     }
  449.     
  450.     DrawPicture(ThePICT,&AreaDataPtr->PICTRect); 
  451.     SaveFore(&OldFore);
  452.     SaveBack(&OldBack);
  453.     PmForeColor(AreaDataPtr->TextFGColor);
  454.     PmBackColor(AreaDataPtr->TextBGColor);
  455.     EraseRect(&(AreaDataPtr->TextRect));
  456.     
  457.     text = AreaDataPtr->TextTEHnd;
  458.     savePort = (*text)->inPort;
  459.     GetPort(&((*text)->inPort));
  460.     TEUpdate(&(AreaDataPtr->TextRect),text);
  461.     (*text)->inPort = savePort;
  462.     RestoreFore(&OldFore);
  463.     RestoreBack(&OldBack);
  464.     
  465.     HUnlock((Handle)AreaData);
  466. }
  467.  
  468. //---------------------------------------------------------------------------------
  469. //
  470. // FUNCTION: AreaKeyDown
  471. //
  472. //---------------------------------------------------------------------------------
  473.  
  474. void AreaKeyDown(AreaHnd AreaData, EventRecord* event)
  475. {
  476.     SBYTE                aChar;
  477.     TEHandle        text;
  478.     ColorSpec        OldFore, OldBack;
  479.     SWORD                TextLength;
  480.     SBYTE                *TextPtr;
  481.     
  482.     aChar = (SBYTE)LoWord(event->message & charCodeMask);
  483.     
  484.     if (event->modifiers & cmdKey)
  485.         event->message = kEventNotTaken;
  486.     else if ((*AreaData)->Flags.Enabled)
  487.     {
  488.         SaveFore(&OldFore);
  489.         SaveBack(&OldBack);
  490.         PmForeColor((*AreaData)->TextFGColor);
  491.         PmBackColor((*AreaData)->TextBGColor);
  492.         switch (aChar)
  493.         {
  494.             //v1.1 a1
  495.             //add the following three lines:
  496.             case (char)10: //Enter key
  497.             //v1.1.1a2
  498.             // add the following line:
  499.             case (char)27: //Escape key
  500.             //so we don't swallow the Escape key.
  501.                 event->message = kEventNotTaken;
  502.                 break;
  503.             //so we don't swallow the Enter key.
  504.             
  505.             case '\r': //Return Key
  506.                 event->message = kGoToNextField;
  507.                 break;
  508.             case '\t': //Tab key
  509.                 event->message = (event->modifiers & shiftKey)?kGoToPreviousField:kGoToNextField;
  510.                 break;
  511.             case '\36': // Up arrow
  512.             case '\37': // Down arrow
  513.             {
  514.                 ListHandle    list;
  515.                 TEHandle        text;
  516.                 Cell                CurrCell;
  517.                 Boolean            OneWasSelected;
  518.                 //move up in list
  519.                 CurrCell.h = 0;
  520.                 CurrCell.v = 0;
  521.                 list = (*AreaData)->ListHnd;
  522.                 text = (*AreaData)->TextTEHnd;
  523.                 OneWasSelected = LGetSelect(true,&CurrCell,list);
  524.                 if ((aChar == '\36') && ((CurrCell.v > 0) || (!OneWasSelected)))
  525.                 {
  526.                     CB_SetLstPos(AreaData,CurrCell.v+(!OneWasSelected));
  527.                     (*AreaData)->Flags.Modified = true;
  528.                 }
  529.                 else if ((aChar == '\37') && (CurrCell.v < (*list)->dataBounds.bottom-1))
  530.                 {
  531.                     CB_SetLstPos(AreaData,CurrCell.v+1+OneWasSelected);
  532.                     (*AreaData)->Flags.Modified = true;
  533.                 }
  534.                 if ((*AreaData)->Flags.ListOnKeystroke)
  535.                     AreaShowList(AreaData);
  536.                 (*AreaData)->KeyTick = 0;
  537.                 break;
  538.             }
  539.             default:
  540.             {
  541.                 text = (*AreaData)->TextTEHnd;
  542.                 if((*AreaData)->Flags.CanEdit)
  543.                     TEKey(aChar,text);
  544.                 if((aChar != '\34') && (aChar != '\35'))
  545.                     (*AreaData)->Flags.Modified = true;
  546.                 else if ((*AreaData)->Flags.CanEdit == false)
  547.                     event->message = (aChar == '\34')?kGoToPreviousField:kGoToNextField;
  548.                 if((aChar != '\b') && (aChar != '\34') && (aChar != '\35'))
  549.                 {
  550.                     //Don't open it when user hits backspace, or the left or right arrow
  551.                     if ((*AreaData)->Flags.ListOnKeystroke)
  552.                         AreaShowList(AreaData);
  553.                     if((*AreaData)->Flags.CanEdit)
  554.                     {
  555.                         TextLength = (*text)->teLength;
  556.                         if(((*text)->selEnd == TextLength) && (TextLength > 0) && ((*AreaData)->Flags.CanFind))
  557.                         {
  558.                             //Search for it
  559.                             HLock((*text)->hText);
  560.                             TextPtr = *((*text)->hText);
  561.                             if(AreaSearchList(TextPtr,TextLength,AreaData))
  562.                                 InvalRect(&(*AreaData)->AreaRect);
  563.                             HUnlock((*text)->hText);
  564.                         }
  565.                     }
  566.                     else
  567.                     {
  568.                         Handle    SearchText;
  569.                         SearchText = (Handle)(*AreaData)->SearchTextHandle;
  570.                         if (TickCount() - (*AreaData)->KeyTick > GetDblTime())
  571.                             (*AreaData)->SearchTextLength = 0;
  572.                         if (++((*AreaData)->SearchTextLength) > (*AreaData)->SearchTextSize) // too big for Text Handle
  573.                         {
  574.                             (*AreaData)->SearchTextSize += 5;
  575.                             SetHandleSize(SearchText, (*AreaData)->SearchTextSize);
  576.                         }
  577.                         (*SearchText)[(*AreaData)->SearchTextLength-1] = aChar;
  578.                         HLock(SearchText);
  579.                         if(AreaSearchList(*SearchText,(*AreaData)->SearchTextLength,AreaData))
  580.                             InvalRect(&(*AreaData)->AreaRect);
  581.                         HUnlock(SearchText);
  582.                         (*AreaData)->KeyTick = TickCount();
  583.                     }
  584.                 }
  585.             }
  586.         }
  587.         RestoreFore(&OldFore);
  588.         RestoreBack(&OldBack);
  589.     }
  590.     else
  591.         event->message = kEventNotTaken;
  592. }
  593.  
  594.  
  595. //---------------------------------------------------------------------------------
  596. //
  597. // FUNCTION: AreaSearchList
  598. //
  599. //---------------------------------------------------------------------------------
  600.  
  601. Boolean AreaSearchList(SBYTE *TextPtr, SWORD TextLength, AreaHnd AreaDataHnd)
  602. {
  603.     Cell                        SearchCell,OldCell;
  604.     register SWORD    i,j;
  605.     register SWORD    MaxCells;
  606.     Ptr                            CellDataPtr;
  607.     SWORD                        offset,len;
  608.     Boolean                    Found;
  609.     TEHandle                text;
  610.     ListHandle            list;
  611.  
  612.     Found = false;
  613.     text = (*AreaDataHnd)->TextTEHnd;
  614.     list = (*AreaDataHnd)->ListHnd;
  615.     SearchCell.h = SearchCell.v = 0;
  616.     MaxCells = (*list)->dataBounds.bottom;
  617.     
  618.     HLock((Handle)(*list)->cells);
  619.     CellDataPtr = *((*list)->cells);
  620.     for (i=0; i<MaxCells; i++) // Cells are zero-relative
  621.     {
  622.         SearchCell.v = i;
  623.         LGetCellDataLocation(&offset,&len,SearchCell,list);
  624.         if (TextLength <= len) // if it's too long, forget it!
  625.         {
  626.             Found = true;  // assume so until we prove otherwise.
  627.             for (j=0; j<TextLength; j++) // character positions are also zero relative
  628.             {
  629.                 if((TextPtr[j] & '_') != (CellDataPtr[offset+j] & '_'))
  630.                 {
  631.                     Found = false;
  632.                     j = TextLength;
  633.                 }
  634.             }
  635.         }
  636.         if (Found)
  637.         {
  638.             // Found it... let's display it.
  639.             if((*AreaDataHnd)->Flags.CanFill)
  640.             {
  641.                 LGetCellDataLocation(&offset,&len,SearchCell,list);
  642.                 TEDeactivate(text); // This is to eliminate the flicker of the insertion point.
  643.                 TESetText(CellDataPtr+offset,len,text);
  644.                 if((*AreaDataHnd)->Flags.CanEdit)
  645.                     TESetSelect(TextLength,len,text);
  646.                 else
  647.                     TESetSelect(0,32767,text);
  648.                 TEActivate(text);
  649.             }
  650.             // Set the Selection
  651.             OldCell.v = OldCell.h = 0;
  652.             while(LGetSelect(true,&OldCell,list))
  653.                 LSetSelect(false,OldCell,list);
  654.             LSetSelect(true,SearchCell,list);
  655.             LAutoScroll(list);
  656.             i = MaxCells; // Stop looking; we found it!
  657.         }
  658.     }
  659.     HUnlock((Handle)(*list)->cells);
  660.     return Found;
  661. }
  662.  
  663. //---------------------------------------------------------------------------------
  664. //
  665. // FUNCTION: AreaSelect
  666. //
  667. //---------------------------------------------------------------------------------
  668.  
  669. OSErr AreaSelect(AreaHnd AreaDataHnd, EventRecord *event)
  670. {
  671.     AreaPtr        AreaDataPtr;
  672.     OSErr            err;
  673.     ColorSpec    OldFore,OldBack;
  674.     
  675.     err = noErr;
  676.     
  677.     if((*AreaDataHnd)->Flags.Enabled)
  678.     {
  679.         HLock((Handle)AreaDataHnd);
  680.         AreaDataPtr = *AreaDataHnd;
  681.                 
  682.         //v1.0.1  changed following block:
  683.         //if((AreaDataPtr->Flags.ListOnActivate) && 
  684.         //        (TickCount() - (*AreaDataHnd)->DeactivateTick > GetDblTime()))
  685.         //{
  686.         //    err = AreaShowList(AreaDataHnd); // DROP DOWN THE LIST!!
  687.         //}
  688.         //to:
  689.         if(TickCount() - (*AreaDataHnd)->DeactivateTick > GetDblTime())
  690.         {
  691.             AreaDataPtr->Flags.Modified = false; // start w/ clean slate when selected
  692.             if(AreaDataPtr->Flags.ListOnActivate) 
  693.             {
  694.                 err = AreaShowList(AreaDataHnd); // DROP DOWN THE LIST!!
  695.             }
  696.         }
  697.         //because clicking a button causes deselect/select combination.  Therefore,
  698.         //clicking a button made us think we were no longer modified, even when we
  699.         //were.
  700.         
  701.         if (err == noErr)
  702.         {
  703.             if(AreaDataPtr->Flags.Visible)
  704.             {
  705.                 SaveFore(&OldFore);
  706.                 SaveBack(&OldBack);
  707.                 PmForeColor(AreaDataPtr->TextFGColor);
  708.                 PmBackColor(AreaDataPtr->TextBGColor);
  709.                 TEActivate(AreaDataPtr->TextTEHnd);
  710.                 AreaSelectAll(AreaDataHnd);
  711.                 RestoreFore(&OldFore);
  712.                 RestoreBack(&OldBack);
  713.             }
  714.         }    
  715.         if(err == noErr)
  716.         {
  717.             AreaDataPtr->Flags.Active = true;
  718.             InvalRect(&(AreaDataPtr->AreaRect));
  719.             AreaDataPtr->ActivateTick = TickCount();
  720.         }
  721.     }
  722.     else
  723.         event->message = kGoToNextField;
  724.  
  725.     //v1.0.1 moved following line into block above:
  726.     //AreaDataPtr->Flags.Modified = false; // start w/ clean slate when selected
  727.     HUnlock((Handle)AreaDataHnd);
  728.     
  729.     return err;
  730. }
  731.  
  732.  
  733. //---------------------------------------------------------------------------------
  734. //
  735. // FUNCTION: AreaDeselect
  736. //
  737. //---------------------------------------------------------------------------------
  738.  
  739. void AreaDeselect(AreaHnd AreaDataHnd)
  740. {
  741.     AreaPtr                    AreaDataPtr;
  742.     ColorSpec                OldFore,OldBack;
  743.     
  744.     HLock((Handle)AreaDataHnd);
  745.     AreaDataPtr = *AreaDataHnd;
  746.     
  747.     SaveFore(&OldFore);
  748.     SaveBack(&OldBack);
  749.     PmForeColor((*AreaDataHnd)->TextFGColor);
  750.     PmBackColor((*AreaDataHnd)->TextBGColor);
  751.     TEDeactivate(AreaDataPtr->TextTEHnd);
  752.     RestoreFore(&OldFore);
  753.     RestoreBack(&OldBack);
  754.     if(AreaDataPtr->Flags.Open)
  755.         AreaHideList(AreaDataHnd); // CLOSE THE LIST BOX
  756.     AreaDataPtr->Flags.Active = false;
  757.     InvalRect(&(AreaDataPtr->AreaRect)); // redraw it
  758.     AreaDataPtr->Flags.Active = false;
  759.     AreaDataPtr->DeactivateTick = TickCount();
  760.  
  761.     HUnlock((Handle)AreaDataHnd);
  762. }
  763.  
  764.  
  765. //---------------------------------------------------------------------------------
  766. //
  767. // FUNCTION: AreaCut
  768. //
  769. //---------------------------------------------------------------------------------
  770.  
  771. void AreaCut(AreaHnd AreaDataHnd)
  772. {
  773.     AreaCopy(AreaDataHnd);
  774.     AreaClear(AreaDataHnd);
  775. }
  776.  
  777.  
  778. //---------------------------------------------------------------------------------
  779. //
  780. // FUNCTION: AreaCopy
  781. //
  782. //---------------------------------------------------------------------------------
  783.  
  784. void AreaCopy(AreaHnd AreaDataHnd)
  785. {
  786.     TEHandle    text;
  787.     XHANDLE        chars;
  788.     SLONG            selSize;
  789.     
  790.     text = (*AreaDataHnd)->TextTEHnd;
  791.     chars = TEGetText(text);
  792.     if (chars)
  793.     {
  794.         selSize = (*text)->selEnd - (*text)->selStart;
  795.         if (selSize)
  796.         {
  797.             ZeroScrap();
  798.             HLock((Handle)chars);
  799.             PutScrap(selSize,'TEXT',(XPOINTER)&(*chars)[(*text)->selStart]);
  800.             HUnlock((Handle)chars);
  801.         }
  802.     }
  803. }
  804.  
  805.  
  806. //---------------------------------------------------------------------------------
  807. //
  808. // FUNCTION: AreaPaste
  809. //
  810. //---------------------------------------------------------------------------------
  811.  
  812. void AreaPaste(AreaHnd AreaDataHnd)
  813. {
  814.     ColorSpec    OldFore,OldBack;
  815.     XHANDLE        chars;
  816.     SLONG            offset,size;
  817.  
  818.     if ((*AreaDataHnd)->Flags.CanEdit)
  819.     {
  820.         SaveFore(&OldFore);
  821.         SaveBack(&OldBack);
  822.         PmForeColor((*AreaDataHnd)->TextFGColor);
  823.         PmBackColor((*AreaDataHnd)->TextBGColor);
  824.     
  825.         chars = (XHANDLE)NewHandle(0);
  826.         if (chars)
  827.         {
  828.             size = GetScrap(chars,'TEXT',&offset);
  829.             HLock((Handle)chars);
  830.             TESetText(*chars,size,(*AreaDataHnd)->TextTEHnd);
  831.             HUnlock((Handle)chars);
  832.             DisposeHandle((Handle)chars);
  833.             InvalRect(&((*AreaDataHnd)->AreaRect));
  834.         }
  835.     
  836.         RestoreFore(&OldFore);
  837.         RestoreBack(&OldBack);
  838.     }
  839. }
  840.  
  841.  
  842. //---------------------------------------------------------------------------------
  843. //
  844. // FUNCTION: AreaClear
  845. //
  846. //---------------------------------------------------------------------------------
  847.  
  848. void AreaClear(AreaHnd AreaDataHnd)
  849. {
  850.     ColorSpec    OldFore,OldBack;
  851.  
  852.     if((*AreaDataHnd)->Flags.CanEdit)
  853.     {
  854.         SaveFore(&OldFore);
  855.         SaveBack(&OldBack);
  856.         PmForeColor((*AreaDataHnd)->TextFGColor);
  857.         PmBackColor((*AreaDataHnd)->TextBGColor);
  858.         TEDelete((*AreaDataHnd)->TextTEHnd);
  859.         RestoreFore(&OldFore);
  860.         RestoreBack(&OldBack);
  861.     }
  862. }
  863.  
  864.  
  865. //---------------------------------------------------------------------------------
  866. //
  867. // FUNCTION: AreaSelectAll
  868. //
  869. //---------------------------------------------------------------------------------
  870.  
  871. void AreaSelectAll(AreaHnd AreaDataHnd)
  872. {
  873.     ColorSpec    OldFore,OldBack;
  874.  
  875.     SaveFore(&OldFore);
  876.     SaveBack(&OldBack);
  877.     PmForeColor((*AreaDataHnd)->TextFGColor);
  878.     PmBackColor((*AreaDataHnd)->TextBGColor);
  879.     TESetSelect(0,32767,(*AreaDataHnd)->TextTEHnd);
  880.     RestoreFore(&OldFore);
  881.     RestoreBack(&OldBack);
  882. }
  883.  
  884.  
  885. //---------------------------------------------------------------------------------
  886. //
  887. // FUNCTION: AreaShowList
  888. //
  889. //---------------------------------------------------------------------------------
  890.  
  891. OSErr AreaShowList(AreaHnd AreaDataHnd)
  892. {
  893.     Boolean    wasOpen;
  894.     
  895.     wasOpen = (*AreaDataHnd)->Flags.Open;
  896.     (*AreaDataHnd)->Flags.Open = true;
  897.     if(!wasOpen)
  898.     {
  899.         ParameterBlock    block;
  900.         PackHnd        PackDataHnd;
  901.         WindowPtr ListWindow;
  902.         GrafPtr            savePort;
  903.         AreaPtr        AreaDataPtr;
  904.         
  905.         PackDataHnd = GetPackDataHnd();
  906.         (*PackDataHnd)->CurrAreaHnd = AreaDataHnd;
  907.         ListWindow = (*PackDataHnd)->ListWindow;
  908.         
  909.         HLock((Handle)AreaDataHnd);
  910.         AreaDataPtr = *AreaDataHnd;
  911.         
  912.         CalcListRect(AreaDataPtr);
  913.         MoveWindow(ListWindow,AreaDataPtr->ListRect.left,AreaDataPtr->ListRect.top,false);
  914.         SizeWindow(ListWindow,AreaDataPtr->ListRect.right-AreaDataPtr->ListRect.left,
  915.                                                     AreaDataPtr->ListRect.bottom-AreaDataPtr->ListRect.top,
  916.                                                     false);
  917.         GetPort(&savePort);
  918.         SetPort(ListWindow);
  919.         PmForeColor(AreaDataPtr->ListFGColor);
  920.         PmBackColor(AreaDataPtr->ListBGColor);
  921.         TextFont(AreaDataPtr->ListFont);
  922.         TextSize(AreaDataPtr->ListSize);
  923.         TextFace(AreaDataPtr->ListStyle);
  924.         SetPort(savePort);
  925.         InvalRect(&AreaDataPtr->AreaRect);
  926.         ShowWindow(ListWindow);
  927.         SelectWindow(ListWindow);
  928.         LAutoScroll(AreaDataPtr->ListHnd);
  929.         block.fParam1 = (*PackDataHnd)->ListProcID;
  930.         HUnlock((Handle)AreaDataHnd);
  931.         CALL4D(kEX_UNFREEZE,&block);
  932.     }
  933.     return noErr;
  934. }
  935.  
  936.  
  937. //---------------------------------------------------------------------------------
  938. //
  939. // FUNCTION: AreaHideList
  940. //
  941. //---------------------------------------------------------------------------------
  942.  
  943. void AreaHideList(AreaHnd AreaDataHnd)
  944. {
  945.     Boolean    wasOpen;
  946.     
  947.     wasOpen = (*AreaDataHnd)->Flags.Open;
  948.     (*AreaDataHnd)->Flags.Open = false;
  949.     if(wasOpen)
  950.     {
  951.         //v1.1
  952.         // moved following line to autoKey event handler:
  953.         //ParameterBlock    block;
  954.         // so that even ComboBoxListMouseDown can pause the process.
  955.         PackHnd        PackDataHnd;
  956.  
  957.         PackDataHnd = GetPackDataHnd();
  958.         //v1.1 a1
  959.         //added the following line:
  960.         LActivate(false, (*AreaDataHnd)->ListHnd);
  961.         //so that we don't have more than one active list at a time.  This was
  962.         //causing dead (or partially-dead) scroll bars.
  963.         
  964.         HideWindow((*PackDataHnd)->ListWindow);
  965.         MoveWindow((*PackDataHnd)->ListWindow,0,0,false);
  966.         SizeWindow((*PackDataHnd)->ListWindow,1,1,false);
  967.         InvalRect(&(*AreaDataHnd)->AreaRect);
  968.         
  969.         //v1.1
  970.         // added the following line:
  971.         PostKey((unsigned long)'@', (unsigned long) cmdKey,true);
  972.         // to cause a user event that triggers kCallTheScript
  973.         
  974.         //v1.1
  975.         // moved the following 2 lines to autoKey event handler:
  976.         //block.fParam1 = (*PackDataHnd)->ListProcID;
  977.         //CALL4D(kEX_FREEZE_PROCESS,&block);
  978.         // so that even ComboBoxListMouseDown can pause the process.
  979.     }
  980. }
  981.  
  982.  
  983. //---------------------------------------------------------------------------------
  984. //
  985. // FUNCTION: GetMouseLoc
  986. //
  987. //---------------------------------------------------------------------------------
  988.  
  989. MouseLocType GetMouseLoc(AreaHnd AreaData, EventRecord* event)
  990. {
  991.     if(PtInRect(event->where, &((*AreaData)->TextRect)))
  992.         return kInText;
  993.     else if(PtInRect(event->where, &((*AreaData)->PICTRect)))
  994.         return kInPICT;
  995.     else
  996.         return kOutside;
  997. }
  998.  
  999.  
  1000. //---------------------------------------------------------------------------------
  1001. //
  1002. // FUNCTION: CalcTextRect
  1003. //
  1004. //---------------------------------------------------------------------------------
  1005.  
  1006. void CalcTextRect (AreaPtr AreaDataPtr)
  1007. {
  1008.     int                            TopBorder,RightBorder;
  1009.     FontInfo                FntInfo;
  1010.     GrafPtr                    CurrGrafPort;
  1011.     TEHandle                text;
  1012.         
  1013.     TopBorder = AreaDataPtr->PixLead;
  1014.     RightBorder = AreaDataPtr->PixGap
  1015.                                 + AreaDataPtr->PICTRect.right
  1016.                                 - AreaDataPtr->PICTRect.left;
  1017.     
  1018.     CurrGrafPort = AreaDataPtr->AreaGrafPort;
  1019.     TextFont(AreaDataPtr->TextFont);
  1020.     TextSize(AreaDataPtr->TextSize);
  1021.     TextFace((Style)(Byte)(AreaDataPtr->TextStyle));
  1022.     GetFontInfo(&(FntInfo));
  1023.     TextFont(CurrGrafPort->txFont);
  1024.     TextSize(CurrGrafPort->txSize);
  1025.     TextFace(CurrGrafPort->txFace);
  1026.     
  1027.     AreaDataPtr->TextRect.top = AreaDataPtr->AreaRect.top + TopBorder;
  1028.     AreaDataPtr->TextRect.left = AreaDataPtr->AreaRect.left;
  1029.     AreaDataPtr->TextRect.bottom = AreaDataPtr->TextRect.top 
  1030.                                                                     + FntInfo.ascent 
  1031.                                                                     + FntInfo.descent;
  1032.     AreaDataPtr->TextRect.right = AreaDataPtr->AreaRect.right - RightBorder;
  1033.  
  1034.     // make sure the text rectangle is inside the area rectangle
  1035.     SectRect(&(AreaDataPtr->TextRect),&(AreaDataPtr->AreaRect),&(AreaDataPtr->TextRect));
  1036.     
  1037.     text = AreaDataPtr->TextTEHnd;
  1038.     //v1.1.1
  1039.     // added the following two lines:
  1040.     if (text)
  1041.     {
  1042.     // because CalcTextRect is called before AreaDataPtr->TextTEHnd is created
  1043.         BlockMove(&(AreaDataPtr->TextRect),&((*text)->destRect),sizeof(Rect));
  1044.         BlockMove(&(AreaDataPtr->TextRect),&((*text)->viewRect),sizeof(Rect));
  1045.     //v1.1.1
  1046.     // added the following line:
  1047.     }
  1048.     // to close the above block
  1049.  
  1050. }
  1051.  
  1052.  
  1053. //---------------------------------------------------------------------------------
  1054. //
  1055. // FUNCTION: CalcListRect
  1056. //
  1057. //---------------------------------------------------------------------------------
  1058.  
  1059. void CalcListRect(AreaPtr AreaDataPtr)
  1060. {
  1061.     GrafPtr        CurrGrafPort;
  1062.     FontInfo    FntInfo;
  1063.     SWORD            CurrFont,CurrSize,CurrFace,RectHeight;
  1064.     GDHandle    screenGD;
  1065.     Rect            screenRect,GlobalAreaRect;
  1066.     Point            GlobalTopLeft;
  1067.     
  1068.     // determine the height of a row in the list
  1069.     GetPort(&CurrGrafPort);
  1070.     CurrFont = CurrGrafPort->txFont;
  1071.     CurrSize = CurrGrafPort->txSize;
  1072.     CurrFace = CurrGrafPort->txFace;
  1073.     TextFont(AreaDataPtr->ListFont);
  1074.     TextSize(AreaDataPtr->ListSize);
  1075.     TextFace(AreaDataPtr->ListStyle);
  1076.     GetFontInfo(&FntInfo);
  1077.     TextFont(CurrFont);
  1078.     TextSize(CurrSize);
  1079.     TextFace(CurrFace);
  1080.     
  1081.     // calculate the height of the list rectangle
  1082.     RectHeight = (FntInfo.ascent + FntInfo.descent + FntInfo.leading) * AreaDataPtr->ListRows;
  1083.     
  1084.     // find bounding rectangle of the main screen
  1085.     screenGD = GetMainDevice();
  1086.     BlockMove(&((*screenGD)->gdRect),&screenRect,sizeof(Rect));
  1087.     
  1088.     // determine global coordinates of area rectangle
  1089.     BlockMove(&(AreaDataPtr->AreaRect),&GlobalAreaRect,sizeof(Rect));
  1090.     GlobalAreaRect.left += AreaDataPtr->LeftGap;
  1091.     GlobalAreaRect.right -= AreaDataPtr->RightGap;
  1092.     GlobalTopLeft.v = GlobalAreaRect.top;
  1093.     GlobalTopLeft.h = GlobalAreaRect.left;
  1094.     SetPort(AreaDataPtr->AreaGrafPort);
  1095.     LocalToGlobal(&GlobalTopLeft);
  1096.     SetPort(CurrGrafPort);
  1097.     OffsetRect(&GlobalAreaRect, GlobalTopLeft.h - GlobalAreaRect.left,
  1098.                                                             GlobalTopLeft.v + AreaDataPtr->TopGap - GlobalAreaRect.top);
  1099.     
  1100.     // position list box just below the area's rectangle
  1101.     AreaDataPtr->ListRect.top = GlobalAreaRect.bottom;
  1102.     AreaDataPtr->ListRect.left = GlobalAreaRect.left;
  1103.     AreaDataPtr->ListRect.right = GlobalAreaRect.right;
  1104.     AreaDataPtr->ListRect.bottom = AreaDataPtr->ListRect.top + RectHeight;
  1105.     
  1106.     if(AreaDataPtr->ListRect.bottom > screenRect.bottom)
  1107.     {
  1108.         // the list box goes below the bottom of the screen, so put it above the area rectangle
  1109.         OffsetRect(&(AreaDataPtr->ListRect),0,
  1110.                             -(AreaDataPtr->TopGap+2+RectHeight+(GlobalAreaRect.bottom-GlobalAreaRect.top)));
  1111.     }
  1112.     if(AreaDataPtr->ListHnd)
  1113.     {
  1114.         (*(AreaDataPtr->ListHnd))->indent.v = FntInfo.ascent;
  1115.         (*(AreaDataPtr->ListHnd))->cellSize.v = FntInfo.ascent + FntInfo.descent + FntInfo.leading;
  1116.         LSize(AreaDataPtr->ListRect.right - AreaDataPtr->ListRect.left - kScrollBarWidth,
  1117.                         AreaDataPtr->ListRect.bottom - AreaDataPtr->ListRect.top,AreaDataPtr->ListHnd);
  1118.     }
  1119. }
  1120.  
  1121.  
  1122. //---------------------------------------------------------------------------------
  1123. //
  1124. // FUNCTION: RedrawList
  1125. //
  1126. //---------------------------------------------------------------------------------
  1127.  
  1128. void RedrawList(AreaPtr AreaDataPtr)
  1129. {
  1130.     if(AreaDataPtr->Flags.Open)
  1131.     {
  1132.         GrafPtr    savePort;
  1133.         PackHnd    PackDataHnd;
  1134.         
  1135.         GetPort(&savePort);
  1136.         PackDataHnd = GetPackDataHnd();
  1137.         SetPort((*PackDataHnd)->ListWindow);
  1138.         InvalRect(&((*PackDataHnd)->ListWindow->portRect));
  1139.         SetPort(savePort);
  1140.     }
  1141. }
  1142.